﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ttbit.core
{
    //核心资源，尽量弄少一点
    public static class CoreResource
    {

        const string color_fs = @"#version 300 es
precision mediump float;

in vec4 vcolor0;//input from vs

layout(location = 0) out vec4 fragColor;//pipeline output

uniform vec4 color; 

void main()
{
    fragColor = vcolor0 * color;
}
";
        const string basevs = @"#version 300 es
layout(location = 0) in vec3 vPosition;//pipeline attribute
layout(location = 1) in vec2 vUV;//pipeline attribute
layout(location = 2) in vec4 vColor;//pipeline attribute
layout(location = 3) in vec2 vUV2;//pipeline attribute
layout(location = 4) in vec2 vUVPal;//pipeline attribute
out vec2 vtex0;//output to fs
out vec2 vtex1;//output to fs
flat out vec2 vpalpos;//output to fs
out vec4 vcolor0;//output to fs
//uniform vec2 pixelScale;
//uniform vec2 pixelOffset;
uniform mat3 matWorld;
uniform mat3 matView;
uniform mat3 matProj;//instead pixelXXX
void main()
{
    //mat3x3 matProj;
    //matProj[0][0] = pixelScale.x;
    //matProj[1][1] = pixelScale.y;
    //matProj[0][2] = pixelOffset.x;
    //matProj[1][2] = pixelOffset.y;
    //matProj[2][2] =1.0;

    vec3 pos  =vec3(vPosition.xy,1) * matWorld * matView * matProj ;
    //vec2 pos =vPosition.xy*pixelScale+pixelOffset;
    gl_Position = vec4(pos.xy,vPosition.z,1);//gl_Position is fix name
    vtex0 = vUV;
    vtex1 = vUV2;
    vpalpos =vUVPal;
    vcolor0 = vColor;
}
";
        const string basefs = @"#version 300 es
precision mediump float;
in vec2 vtex0;//input from vs
in vec4 vcolor0;//input from vs
layout(location = 0) out vec4 fragColor;//pipeline output

uniform sampler2D texmain; 
uniform vec4 color; 

void main()
{
    vec4 c= texture(texmain,vtex0)*vcolor0*color;
    fragColor = c;
}
";

        const string grayfs = @"#version 300 es
precision mediump float;
in vec2 vtex0;//input from vs
in vec4 vcolor0;//input from vs

layout(location = 0) out vec4 fragColor;//pipeline output
uniform sampler2D texmain; 
uniform vec4 color; 

void main()
{
    float c=texture(texmain,vtex0).r;
    if(c<1.0/255.0)
       discard;
    vec4 cout = vcolor0 * color;
    cout.a*=c;
    fragColor = cout;
}
";
        const string palfs = @"#version 300 es
precision highp float;
in vec2 vtex0;//input from vs
flat in vec2 vpalpos;//input from vs
in vec4 vcolor0;//input from vs
layout(location = 0) out vec4 fragColor;//pipeline output

uniform sampler2D texmain; 
uniform sampler2D texpal; 
uniform vec4 color; 

void main()
{
    vec4 srcc= texture(texmain,vtex0);

    float lut_u = srcc.r + vpalpos.x;
    float lut_v = vpalpos.y;
   
    vec4 palc= texture(texpal,vec2(lut_u,lut_v));
    vec4 c= palc*vcolor0*color;
    fragColor = c;
}

";
        const string lutfs = @"#version 300 es
precision highp float;
in vec2 vtex0;//input from vs
in vec4 vcolor0;//input from vs
layout(location = 0) out vec4 fragColor;//pipeline output

uniform sampler2D texmain; 
uniform sampler2D texlut; 
uniform vec4 color; 

void main()
{
    vec4 srcc= texture(texmain,vtex0);

    int byter =int(srcc.r*255.0);
    int byteg =int(srcc.g*255.0);
    int byteb =int(srcc.b*255.0);

    float lut_v = float(byteg/4)/63.0f;
    float lut_u = float(byter/8*32 + byteb/8)/1023.0f;

    vec4 lutc= texture(texlut,vec2(lut_u,lut_v));
    vec4 c= lutc*vcolor0*color;
    fragColor = c;
}
";
        const string calclutfs = @"#version 300 es
precision highp float;
in vec2 vtex0;//input from vs

layout(location = 0) out vec4 fragColor;//pipeline output

uniform sampler2D texmain;
uniform sampler2D texpal;
uniform sampler2D texpallab;
float distquick(vec3 left, vec3 right) {
    float x1 = (left.x - right.x);
    float y1 = (left.y - right.y);
    float z1 = (left.z - right.z);
    return sqrt(x1 * x1 + y1 * y1 + z1 * z1);
}
const float PI = 3.14159274;
// float degrees(float n) {
//     return n * (180.0 / PI);
// }
// float radians(float n) {
//     return n * (PI / 180.0);
// }

float hp_f(float x, float y) //(7)
{
    if(x == 0.0 && y == 0.0)
        return 0.0;
    else {
        float tmphp = degrees(atan(y, x));
        if(tmphp >= 0.0)
            return tmphp;
        else
            return tmphp + 360.0;
    }
}

float dhp_f(float C1, float C2, float h1p, float h2p) //(10)
{
    if(C1 * C2 == 0.0)
        return 0.0;
    else if(abs(h2p - h1p) <= 180.0)
        return h2p - h1p;
    else if((h2p - h1p) > 180.0)
        return (h2p - h1p) - 360.0;
    else if((h2p - h1p) < -180.0)
        return (h2p - h1p) + 360.0;
    else {
        return 0.0;
    }
}

float a_hp_f(float C1, float C2, float h1p, float h2p) { //(14)
    if(C1 * C2 == 0.0)
        return h1p + h2p;
    else if(abs(h1p - h2p) <= 180.0)
        return (h1p + h2p) / 2.0;
    else if((abs(h1p - h2p) > 180.0) && ((h1p + h2p) < 360.0))
        return (h1p + h2p + 360.0) / 2.0;
    else if((abs(h1p - h2p) > 180.0) && ((h1p + h2p) >= 360.0))
        return (h1p + h2p - 360.0) / 2.0;
    else {
        return  h1p + h2p;
    }
}
float ciede2000(vec3 c1, vec3 c2) {
            /**
             * Implemented as in ""The CIEDE2000 Color-Difference Formula:
             * Implementation Notes, Supplementary Test Data, and Mathematical Observations""
             * by Gaurav Sharma, Wencheng Wu and Edul N. Dalal.
             */

            // Get L,a,b values for color 1
    float L1 = c1.x;
    float a1 = c1.y;
    float b1 = c1.z;

            // Get L,a,b values for color 2
    float L2 = c2.x;
    float a2 = c2.y;
    float b2 = c2.z;

            // Weight factors
    float kL = 1.0;
    float kC = 1.0;
    float kH = 1.0;

            /**
             * Step 1: Calculate C1p, C2p, h1p, h2p
             */
    float C1 = sqrt(pow(a1, 2.0) + pow(b1, 2.0)); //(2)
    float C2 = sqrt(pow(a2, 2.0) + pow(b2, 2.0)); //(2)

    float a_C1_C2 = (C1 + C2) / 2.0;             //(3)

    float G = 0.5 * (1.0 - sqrt(pow(a_C1_C2, 7.0) /
        (pow(a_C1_C2, 7.0) + pow(25.0, 7.0)))); //(4)

    float a1p = (1.0 + G) * a1; //(5)
    float a2p = (1.0 + G) * a2; //(5)

    float C1p = sqrt(pow(a1p, 2.0) + pow(b1, 2.0)); //(6)
    float C2p = sqrt(pow(a2p, 2.0) + pow(b2, 2.0)); //(6)

    float h1p = hp_f(b1, a1p); //(7)
    float h2p = hp_f(b2, a2p); //(7)

            /**
             * Step 2: Calculate dLp, dCp, dHp
             */
    float dLp = L2 - L1; //(8)
    float dCp = C2p - C1p; //(9)

    float dhp = dhp_f(C1, C2, h1p, h2p); //(10)
    float dHp = 2.0 * sqrt(C1p * C2p) * sin(radians(dhp) / 2.0); //(11)

            /**
             * Step 3: Calculate CIEDE2000 Color-Difference
             */
    float a_L = (L1 + L2) / 2.0; //(12)
    float a_Cp = (C1p + C2p) / 2.0; //(13)

    float a_hp = a_hp_f(C1, C2, h1p, h2p); //(14)
    float T = 1.0 - 0.17 * cos(radians(a_hp - 30.0)) + 0.24 * cos(radians(2.0 * a_hp)) +
        0.32 * cos(radians(3.0 * a_hp + 6.0)) - 0.20 * cos(radians(4.0 * a_hp - 63.0)); //(15)
    float d_ro = 30.0 * exp(-(pow((a_hp - 275.0) / 25.0, 2.0))); //(16)
    float RC = sqrt((pow(a_Cp, 7.0)) / (pow(a_Cp, 7.0) + pow(25.0, 7.0)));//(17)
    float SL = 1.0 + ((0.015 * pow(a_L - 50.0, 2.0)) /
        sqrt(20.0 + pow(a_L - 50.0, 2.0)));//(18)
    float SC = 1.0 + 0.045 * a_Cp;//(19)
    float SH = 1.0 + 0.015 * a_Cp * T;//(20)
    float RT = -2.0 * RC * sin(radians(2.0 * d_ro));//(21)
    float dE = sqrt(pow(dLp / (SL * kL), 2.0) + pow(dCp / (SC * kC), 2.0) +
        pow(dHp / (SH * kH), 2.0) + RT * (dCp / (SC * kC)) *
        (dHp / (SH * kH))); //(22)

    return dE;
}
void main() {
    vec4 srcc = texture(texmain, vtex0);

    float dist = 10000.0;
    int index = 0;
    for(int i = 1; i < 256; i++) {
        float u = float(i) / 255.0;
        vec4 destc = texture(texpallab, vec2(u, 0.0));
        //float dist2 = distquick(destc.xyz, srcc.xyz);
        float dist2 = ciede2000(destc.xyz, srcc.xyz);

        if(dist2 < dist) {
            dist = dist2;
            index = i;
        }
    }

    float urgb = float(index) / 255.0;
    vec4 c = texture(texpal, vec2(urgb, 0.0));
    c.a = urgb;
    fragColor = c;
}

";
        //注意 calclutfs 不要开启alphablend，这东西顶不住的
        public static void Init()
        {
            ////挪到文件初始化，方便调试
            //ShaderPool.LoadByJson("./baseres/shaders/shaderdesc.json");
            //var _colorvs = Shaders.AddShader("color", Shaders.ShaderType.VertexShader, color_vs);
            //var _colorfs = Shaders.AddShader("color", Shaders.ShaderType.FragmentShader, color_fs);
            //Shaders.LinkShader("color", _colorvs, _colorfs);

            var _basevs = ShaderPool.AddShader("base", ShaderPool.ShaderType.VertexShader, basevs);
            var _basefs = ShaderPool.AddShader("base", ShaderPool.ShaderType.FragmentShader, basefs);
            ShaderPool.LinkShader("base", _basevs, _basefs);

            var _colorfs = ShaderPool.AddShader("color", ShaderPool.ShaderType.FragmentShader, color_fs);
            ShaderPool.LinkShader("color", _basevs, _colorfs);

            var _fontfs = ShaderPool.AddShader("gray", ShaderPool.ShaderType.FragmentShader, grayfs);
            ShaderPool.LinkShader("gray", _basevs, _fontfs);

            var _palfs = ShaderPool.AddShader("pal", ShaderPool.ShaderType.FragmentShader, palfs);
            ShaderPool.LinkShader("pal", _basevs, _palfs);

            var _lutfs = ShaderPool.AddShader("lut", ShaderPool.ShaderType.FragmentShader, lutfs);
            ShaderPool.LinkShader("lut", _basevs, _lutfs);

            var _calclutfs = ShaderPool.AddShader("calclut", ShaderPool.ShaderType.FragmentShader, calclutfs);
            ShaderPool.LinkShader("calclut", _basevs, _calclutfs);

            TexturePool.Init();
            //SpritePool.Init();


            //using (var ms = Env.platform.CoreAssetReadAll("resource/core/ASCII12.bin"))
            //{
            //    Font font = CoreLoadTool.LoadAscII(ms, 12, SpritePool.DefaultGray);
            //    font.name = "asc12";
            //    FontPool.AddNamedFont("asc12", font);
            //}



        }

    }
}
